package com.ruihu.admin.module.business.tasknode.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruihu.admin.common.anno.MethodLog;
import com.ruihu.admin.common.constant.ResponseCodeConst;
import com.ruihu.admin.common.domain.PageResultDTO;
import com.ruihu.admin.common.domain.ResponseDTO;
import com.ruihu.admin.module.business.tasknode.constant.TaskNodeResponseCodeConst;
import com.ruihu.admin.module.business.tasknode.dao.DefectTypeDao;
import com.ruihu.admin.module.business.tasknode.dao.NodeInstProcessDefectDao;
import com.ruihu.admin.module.business.tasknode.dao.SubTaskNodeInstDao;
import com.ruihu.admin.module.business.tasknode.domain.dto.*;
import com.ruihu.admin.module.business.tasknode.domain.entity.DefectTypeEntity;
import com.ruihu.admin.module.business.tasknode.domain.entity.NodeDefectRelationEntity;
import com.ruihu.admin.module.business.tasknode.domain.entity.NodeInstProcessDefectEntity;
import com.ruihu.admin.module.business.tasknode.domain.entity.SubTaskNodeInstEntity;
import com.ruihu.admin.module.business.tasknode.domain.vo.DefectTypeVO;
import com.ruihu.admin.module.business.tasknode.domain.vo.DefectTypeExcelVO;
import com.ruihu.admin.util.PageUtil;
import com.ruihu.admin.util.BeanUtil;
import com.ruihu.admin.util.RequestTokenUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * [ 缺陷类型配置 ]
 *
 * @author Tony
 * @version 1.0
 * @company 瑞虎（南京）信息技术有限公司
 * @copyright (c)  瑞虎（南京）信息技术有限公司Inc. All rights reserved.
 * @date 2022-09-04 10:46:11
 * @since JDK1.8
 */
@Service
public class DefectTypeService {

    @Autowired
    private DefectTypeDao defectTypeDao;

    @Autowired
    private NodeDefectRelationService nodeDefectRelationService;

    @Autowired
    private NodeInstProcessDefectDao nodeInstProcessDefectDao;

    /**
     * 根据id查询
     */
    public DefectTypeEntity getById(Long id){
        return  defectTypeDao.selectById(id);
    }

    /**
     * 分页查询
     * @author Tony
     * @date 2022-09-04 10:46:11
     */
    @MethodLog
    public ResponseDTO<PageResultDTO<DefectTypeVO>> queryByPage(DefectTypeQueryDTO queryDTO) {
        Page page = PageUtil.convert2QueryPage(queryDTO);
        List<DefectTypeVO> voList = defectTypeDao.queryByPage(page, queryDTO);
        page.setRecords(voList);
        PageResultDTO<DefectTypeVO> pageResultDTO = PageUtil.convert2PageResult(page);
        return ResponseDTO.succData(pageResultDTO);
    }

    /**
     * 查询缺陷类型列表
     * @param queryDTO
     * @return
     */
    @MethodLog
    public ResponseDTO<List<DefectTypeVO>> queryByList(DefectTypeQueryDTO queryDTO) {
        List<DefectTypeDTO> dtoList = this.defectTypeDao.queryByList(queryDTO);
        List<DefectTypeVO> voList = new ArrayList<>(dtoList.size());
        dtoList.stream().forEach(e -> voList.add(DefectTypeVO.convertToDefectTypeVO(e)));
        return ResponseDTO.succData(voList);
    }


    /**
     * 根据TaskNode分组查询缺陷列表
     * @param queryDTO
     * @return
     */
    @MethodLog
    public ResponseDTO<Map<Long, List<DefectTypeVO>>> queryListGroupByTaskNode(DefectTypeQueryDTO queryDTO) {
        List<DefectTypeDTO> dtoList = this.defectTypeDao.queryByList(queryDTO);
        List<DefectTypeVO> voList = new ArrayList<>(dtoList.size());
        dtoList.stream().forEach(e -> voList.add(DefectTypeVO.convertToDefectTypeVO(e)));
        Map<Long, List<DefectTypeVO>> groupList = voList.stream().collect(Collectors.groupingBy(e -> e.getTaskNodeId()));
        return ResponseDTO.succData(groupList);
    }

    /**
     * 添加
     * @author Tony
     * @date 2022-09-04 10:46:11
     */
    @MethodLog
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> add(DefectTypeAddDTO addDTO) {
        QueryWrapper<DefectTypeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("defect_name",addDTO.getDefectName());
        DefectTypeEntity defectTypeEntity = defectTypeDao.selectOne(queryWrapper);
        if (Objects.isNull(defectTypeEntity)) {
            defectTypeEntity = BeanUtil.copy(addDTO, DefectTypeEntity.class);
            defectTypeEntity.setCreateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
            defectTypeDao.insert(defectTypeEntity);
        }
        if(Objects.nonNull(defectTypeEntity)){
            List<NodeDefectRelationEntity> defectRelationEntityList = nodeDefectRelationService.queryByDefectType(NodeDefectRelationDTO.builder()
                    .defectTypeId(defectTypeEntity.getId())
                    .taskNodeId(addDTO.getTaskNodeId()).build());
            if(CollectionUtils.isNotEmpty(defectRelationEntityList)){
                return ResponseDTO.wrap(TaskNodeResponseCodeConst.TASK_NODE_DEFECT_NAME_EXISTS);
            }
        }
        //新增关系表
        NodeDefectRelationAddDTO nodeDefectRelationAddDTO = new NodeDefectRelationAddDTO();
        nodeDefectRelationAddDTO.setDefectTypeId(defectTypeEntity.getId());
        nodeDefectRelationAddDTO.setTaskNodeId(addDTO.getTaskNodeId());
        nodeDefectRelationAddDTO.setCreateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
        nodeDefectRelationService.add(nodeDefectRelationAddDTO);
        return ResponseDTO.succ();
    }

    /**
     * 编辑
     * @author Tony
     * @date 2022-09-04 10:46:11
     */
    @MethodLog
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> update(DefectTypeUpdateDTO updateDTO) {
        List<NodeDefectRelationEntity> defectRelationEntityList = nodeDefectRelationService.queryByDefectType(NodeDefectRelationDTO.builder()
                .defectTypeId(updateDTO.getId())
                .taskNodeId(updateDTO.getTaskNodeId()).build());
        if(CollectionUtils.isNotEmpty(defectRelationEntityList)) {
            // 更新缺陷名称
            DefectTypeEntity defectTypeEntity = this.defectTypeDao.selectById(updateDTO.getId());
            if (Objects.nonNull(defectTypeEntity)) {
                defectTypeEntity.setDefectName(updateDTO.getDefectName());
                defectTypeEntity.setRemark(updateDTO.getRemark());
                this.defectTypeDao.updateById(defectTypeEntity);
                return ResponseDTO.succ();
            } else {
                return ResponseDTO.wrap(TaskNodeResponseCodeConst.DEFECT_TYPE_NOT_EXISTS);
            }
        } else {
            DefectTypeEntity entity = BeanUtil.copy(updateDTO, DefectTypeEntity.class);
            entity.setUpdateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
            entity.setUpdateTime(new Date());
            defectTypeDao.updateByIdIgnoreEmptyValue(entity);
            //先删除关系表
            nodeDefectRelationService.deleteByDefectType(NodeDefectRelationDTO.builder().defectTypeId(updateDTO.getId())
                    .taskNodeId(updateDTO.getTaskNodeId()).build());
            //新增关系表
            NodeDefectRelationAddDTO nodeDefectRelationAddDTO = new NodeDefectRelationAddDTO();
            nodeDefectRelationAddDTO.setDefectTypeId(updateDTO.getId());
            nodeDefectRelationAddDTO.setCreateBy(RequestTokenUtil.getRequestUser().getRequestUserId());
            nodeDefectRelationAddDTO.setTaskNodeId(updateDTO.getTaskNodeId());
            nodeDefectRelationService.add(nodeDefectRelationAddDTO);
            return ResponseDTO.succ();
        }
    }

    /**
     * 删除
     * @author Tony
     * @date 2022-09-04 10:46:11
     */
    @MethodLog
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> delete(DefectTypeDeleteDTO dto) {
        if(Objects.isNull(dto.getId())||Objects.isNull(dto.getTaskNodeId()))
            return ResponseDTO.wrap(TaskNodeResponseCodeConst.DEFECT_TYPE_ID_NULL);
        //首先判断是否被使用，然后再删除
        QueryWrapper<NodeInstProcessDefectEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("defect_type_id",dto.getId());
        List<NodeInstProcessDefectEntity> nodeInstProcessDefectEntityList = this.nodeInstProcessDefectDao.selectList(queryWrapper);
        if(CollectionUtils.isNotEmpty(nodeInstProcessDefectEntityList)){
            return ResponseDTO.wrap(TaskNodeResponseCodeConst.DEFECT_TYPE_HAS_USED);
        }
        //删除缺陷类型
        //defectTypeDao.deleteById(dto.getId());
        //删除关系表
        nodeDefectRelationService.deleteByDefectType(NodeDefectRelationDTO.builder().defectTypeId(dto.getId())
                .taskNodeId(dto.getTaskNodeId()).build());
        return ResponseDTO.succ();
    }

    /**
     * 批量删除
     * @author Tony
     * @date 2022-09-04 10:46:11
     */
    @MethodLog
    @Transactional(rollbackFor = Exception.class)
    public ResponseDTO<String> deleteByIds(List<Long> idList) {
        defectTypeDao.deleteByIdList(idList);
        return ResponseDTO.succ();
    }

    /**
     * 查询全部导出对象
     * @author Tony
     * @date 2022-09-04 10:46:11
     */
    @MethodLog
    public List<DefectTypeExcelVO> queryAllExportData(DefectTypeQueryDTO queryDTO) {
        return defectTypeDao.queryAllExportData( queryDTO);
    }

    /**
     * 批量查询导出对象
     * @author Tony
     * @date 2022-09-04 10:46:11
     */
    @MethodLog
    public List<DefectTypeExcelVO> queryBatchExportData(List<Long> idList) {
        return defectTypeDao.queryBatchExportData(idList);
    }

    /**
     * 统计节点下的类型数
     * @param taskNodeId
     * @return
     */
    public Integer countDefectTypeByNodeId(Long taskNodeId){
        QueryWrapper<DefectTypeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("task_node_id",taskNodeId);
        queryWrapper.eq("is_delete","0");
        Integer count = defectTypeDao.selectCount(queryWrapper);
        return count;
    }

    /**
     * 分组查询缺陷类型
     * @return
     */
    public List<DefectTypeVO> queryDefectType() {
        DefectTypeQueryDTO queryDTO = new DefectTypeQueryDTO();
        List<DefectTypeVO> voList = defectTypeDao.queryByPage(null, queryDTO);
        return voList;
    }
}
